package com.ngender;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * 字符频率统计类
 */
public class CharFreq {
    private long maleTotal = 0;
    private long femaleTotal = 0;
    private long total = 0;
    private final Map<String, double[]> freq = new HashMap<>();

    public CharFreq() {
        loadModel();
    }

    /**
     * 加载字符频率模型
     */
    private void loadModel() {
        try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream("charfreq.csv");
             BufferedReader reader = new BufferedReader(new InputStreamReader(Objects.requireNonNull(inputStream), StandardCharsets.UTF_8))) {

            // 跳过表头
            reader.readLine();

            String line;
            while ((line = reader.readLine()) != null) {
                String[] parts = line.split(",");
                if (parts.length < 3) {
                    continue;
                }

                String character = parts[0];
                long maleCount = Long.parseLong(parts[1]);
                long femaleCount = Long.parseLong(parts[2]);

                maleTotal += maleCount;
                femaleTotal += femaleCount;
                freq.put(character, new double[]{femaleCount, maleCount});
            }

            total = maleTotal + femaleTotal;

            // 转换为概率
            for (Map.Entry<String, double[]> entry : freq.entrySet()) {
                double[] counts = entry.getValue();
                // P(字符|女性)
                counts[0] = counts[0] / femaleTotal;
                // P(字符|男性)
                counts[1] = counts[1] / maleTotal;
            }
        } catch (Exception e) {
            throw new RuntimeException("Failed to load character frequency model", e);
        }
    }

    /**
     * 计算给定名字在特定性别下的概率（分子部分）
     */
    public double probForGender(String firstName, int gender) {
        // 先验概率 P(性别)
        double p = (gender == 0) ? (double) femaleTotal / total : (double) maleTotal / total;

        // 累乘条件概率 ∏ P(字符ᵢ|性别)
        for (int i = 0; i < firstName.length(); i++) {
            String character = String.valueOf(firstName.charAt(i));
            double[] probs = freq.getOrDefault(character, new double[]{0.0, 0.0});
            p *= probs[gender];
        }

        return p;
    }

    /**
     * 预测性别
     */
    public GenderResult guess(String name) {
        if (name == null || name.length() < 2 || name.length() > 3) {
            return new GenderResult(GenderConstants.UNKNOWN, 0.0);
        }

        // 验证中文汉字
        String firstName = name.substring(1);
        for (int i = 0; i < firstName.length(); i++) {
            char c = firstName.charAt(i);
            if (c < '\u4e00' || c > '\u9fa0') {
                return new GenderResult(GenderConstants.UNKNOWN, 0.0);
            }
        }

        // 女性概率分子
        double pf = probForGender(firstName, 0);
        // 男性概率分子
        double pm = probForGender(firstName, 1);

        if (pm > pf) {
            return new GenderResult(GenderConstants.MALE, pm / (pm + pf));
        } else if (pm < pf) {
            return new GenderResult(GenderConstants.FEMALE, pf / (pm + pf));
        } else {
            return new GenderResult(GenderConstants.UNKNOWN, 0.0);
        }
    }

    // Getter方法
    public long getMaleTotal() { return maleTotal; }
    public long getFemaleTotal() { return femaleTotal; }
    public long getTotal() { return total; }
}